﻿#include "Analyzer.h"
#include "Algorithm.h"
#include <json/json.h>
#include <fstream>
#include "Scheduler.h"
#include "Config.h"
#include "Control.h"
#include "Utils/Log.h"
#include "Utils/Request.h"
#include "Utils/Base64.h"
#include "Utils/CalcuIOU.h"
#include "ModelConfig.h"
//#include "DetectObject.h"
#include "GenerateAlarmImage.h"

namespace AVSAnalyzer {

    Analyzer::Analyzer(Scheduler* scheduler, Control* control) :
        mScheduler(scheduler),
        mControl(control)
    {

    }

    Analyzer::~Analyzer()
    {

    }

    bool Analyzer::handleVideoFrame(int64_t frameCount, cv::Mat& image, std::vector<DetectObject>& happenDetects, bool& happen, float& happenScore)
    {
        // 获取算法配置
        const AlgorithmConfig* config = ModelConfig::getInstance().getAlgorithmConfig(mControl->algorithmCode);
        if (!config) {
            LOGE("Failed to get algorithm config for: %s", mControl->algorithmCode.c_str());
            return false;
        }

        // 如果是API类型，使用服务器推理
        // if (config->type == "api") {
        //     return this->postImage2Server(frameCount, image, happenDetects, happen, happenScore);
        // }

        happenDetects.clear();
        happen = false;
        happenScore = 0;

        try {
            // 使用锁保护访问算法实例
            std::lock_guard<std::mutex> lock(mScheduler->mAlgorithmsMtx);

            // 查找匹配的算法实例
            auto it = std::find_if(mScheduler->mAlgorithms.begin(), mScheduler->mAlgorithms.end(),
                [&config](const std::unique_ptr<Algorithm>& algorithm) {
                    return algorithm->getConfig().type == config->type;
                });

            if (it == mScheduler->mAlgorithms.end()) {
                LOGE("Unsupported algorithm type or algorithm not initialized: %s", config->type.c_str());
                return false;
            }

            // 执行目标检测
            if (!(*it)->objectDetect(image, happenDetects)) {
                LOGE("Object detection failed for algorithm type: %s", config->type.c_str());
                return false;
            }

            // 如果检测到目标
            if (!happenDetects.empty())
            {
                //绘制多边形
                cv::polylines(image, mControl->recognitionRegion_points,
                    mControl->recognitionRegion_points.size(), cv::Scalar(0, 0, 255), 4, 8);

                int matchCount = 0;
                for (auto& detect : happenDetects)
                {
                    // 构建目标框的多边形点
                    std::vector<double> object_d;
                    object_d.push_back(detect.x1);
                    object_d.push_back(detect.y1);
                    object_d.push_back(detect.x2);
                    object_d.push_back(detect.y1);
                    object_d.push_back(detect.x2);
                    object_d.push_back(detect.y2);
                    object_d.push_back(detect.x1);
                    object_d.push_back(detect.y2);

                    // 计算IOU
                    double iou = CalcuPolygonIOU(mControl->recognitionRegion_d, object_d);
                    if (iou >= 0.5)
                    {
                        ++matchCount;
                        // // 获取类别名称
                        // if (detect.class_id < mControl->objects_v1_len) {
                        //     detect.class_name = mControl->objects_v1[detect.class_id];

                        //     // 检查是否匹配目标类别
                        //     if (detect.class_name == mControl->objectCode) {
                        //         ++matchCount;
                        //     }
                        // }
                        // else 
                        // {
                        //     LOGE("class error,class_id=%d,objects_v1_len=%d",
                        //         detect.class_id, mControl->objects_v1_len);
                        // }
                    }
                }

                // 如果有匹配的目标，触发报警
                if (matchCount > 0)
                {
                    happen = true;
                    happenScore = 1.0;
                }
            }

            return true;
        }
        catch (const std::exception& e) {
            LOGE("处理视频帧异常: %s", e.what());
            return false;
        }
        catch (const cv::Exception& e) {
            LOGE("OpenCV exception: %s (file: %s, line: %d)", 
                 e.what(), e.file.c_str(), e.line);
            return false;
        }
        catch (...) {
            LOGE("Unknown exception during inference");
            return false;
        }
    }

    bool Analyzer::postImage2Server(int64_t frameCount, cv::Mat& image, std::vector<DetectObject>& happenDetects, bool& happen, float& happenScore)
    {
        Config* config = mScheduler->getConfig();
        int height = mControl->videoHeight;
        int width = mControl->videoWidth;

        std::vector<int> JPEG_QUALITY = { 75 };
        std::vector<uchar> jpg;
        cv::imencode(".jpg", image, jpg, JPEG_QUALITY);
        int JPGBufSize = jpg.size();

        if (JPGBufSize > 0)
        {
            Base64 base64;
            std::string imageBase64;
            base64.encode(jpg.data(), JPGBufSize, imageBase64);

            std::string response;
            Json::Value param;
            param["image_base64"] = imageBase64;
            param["code"] = mControl->code;                 //布控编号
           // param["objectCode"] = mControl->objectCode;
           // param["objects"] = mControl->objects;
            param["recognitionRegion"] = mControl->recognitionRegion;
            param["min_interval"] = mControl->minInterval;

            std::string data = param.toStyledString();
            //int64_t t1 = Common::getCurTimestamp();
            Request request;
            if (request.post(config->algorithmApiUrl.data(), data.data(), response))
            {
                Json::CharReaderBuilder builder;
                const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());

                Json::Value root;
                JSONCPP_STRING errs;

                if (reader->parse(response.data(), response.data() + std::strlen(response.data()), &root, &errs) && errs.empty())
                {
                    if (root["code"].isInt() && root["msg"].isString())
                    {
                        int code = root["code"].asInt();
                        std::string msg = root["msg"].asCString();

                        if (1000 == code)
                        {
                            happenDetects.clear();
                            happen = false;
                            happenScore = 0.0;

                            Json::Value result = root["result"];
                            if (result["happen"].isBool() && result["happenScore"].isDouble()) {
                                happen = result["happen"].asBool();
                                happenScore = result["happenScore"].asFloat();

                                Json::Value result_detects = result["detects"];
                                for (auto i : result_detects) {

                                    int x1 = i["x1"].asInt();
                                    int y1 = i["y1"].asInt();
                                    int x2 = i["x2"].asInt();
                                    int y2 = i["y2"].asInt();
                                    float class_score = i["class_score"].asFloat();
                                    std::string class_name = i["class_name"].asString();

                                    DetectObject detect;
                                    detect.x1 = x1;
                                    detect.y1 = y1;
                                    detect.x2 = x2;
                                    detect.y2 = y2;
                                    detect.class_name = class_name;
                                    detect.class_score = class_score;

                                    happenDetects.push_back(detect);
                                }
                            }
                        }
                        else
                        {
                            LOGE("code=%d,msg=%s", code, msg.data());
                        }
                    }
                    else
                    {
                        LOGE("incorrect return parameter format");
                    }
                }
            }
            else
            {
                happenDetects.clear();
                happen = false;
                happenScore = 0.0;
            }
            //int64_t t2 = Common::getCurTimestamp();        
        }
        return true;
    }
}